#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <string>
#include <unistd.h>
#include <cstring>
#include <pthread.h>
#include "Task.hpp"
#include "ThreadPool.hpp"

using std::cout;
using std::cin;
using std::endl;

#define BACK_LOG 10





class TCP
{
    public:
    TCP():listen_fd_(-1),tp_(new ThreadPool<Task>()){}
    ~TCP()
    {
        if(listen_fd_ >=0)
        {
            close(listen_fd_);
        }
    }

    bool Init()
    {
        listen_fd_=socket(AF_INET,SOCK_STREAM,0);
        if(listen_fd_ < 0)
        {
            perror("Create TCP Socket Failed\n");
            return false;
        }
        cout<<"Create TCP Socket Successed"<<endl;
        return true;
    }

    bool Bind(std::string ip,int port)
    {
        ip_=ip;
        port=port;
        struct sockaddr_in peer;
        memset(&peer,0,sizeof(peer));
        peer.sin_family=AF_INET;
        peer.sin_port=htons(port);
        peer.sin_addr.s_addr=INADDR_ANY;
        if(bind(listen_fd_,(struct sockaddr*)&peer,sizeof(peer)) == 0)
        {
            cout<<"Bind TCP Socket Successed"<<endl;
        }
        else
        {
            perror("Bind TCP Socket Failed\n");
            return false;
        }
        return true;
    }
    bool Listen()
    {
        if(listen(listen_fd_,BACK_LOG) == 0)
        {
            cout<<"Listen TCP Socket Successed"<<endl;
        }
        else
        {
            perror("Listen TCP Socket Failed\n");
            return false;
        }
        return true;
    }

    //这部分提供实现的代码，分割到了Handerl类当中，接下来就是实现线程池。
    // static void* Service(void* arg)
    // {
    //     pthread_detach(pthread_self());
    //     Param* p=(Param*)arg;
    //     int sock_fd=p->sock_fd_;
    //     std::string client_ip=p->client_ip_;
    //     int port=p->port_;
    //     char buffer[1024];
    //     cout<<"jjdkajsd"<<endl;
    //     while(1)
    //     {
    //         ssize_t size=read(sock_fd,buffer,sizeof(buffer)-1);
    //         if(size >0)
    //         {
    //             buffer[size]='\0';
    //             cout<<"["<<client_ip<<" : "<<port<<"] say#"<<buffer<<endl;
    //             write(sock_fd,buffer,size);
    //         }
    //         else if(size ==0 )
    //         {
    //             break;
    //         }
    //         else 
    //         {
    //             perror("Accept TCP Socket Failed\n");
    //             close(sock_fd);
    //             return nullptr;
    //         }
    //     }
    //     close(sock_fd);
    //     cout<<"Client Close Sock_fd"<<endl;
    //     return nullptr;
    // }




    //多线程版本
    bool Start()
    {
        signal(SIGCHLD,SIG_IGN);
        tp_->Init_Thread_Pool();
        while(1)
        {
            struct sockaddr_in peer;
            memset(&peer,0,sizeof(peer));
            socklen_t len=sizeof(peer);
            int sock_fd=accept(listen_fd_,(struct sockaddr*)&peer,&len);
            if(sock_fd < 0)
            {
                perror("Accept TCP Socket Failed\n");
                continue;
            }
            std::string client_ip=inet_ntoa(peer.sin_addr);
            int port=ntohs(peer.sin_port);
            cout<<"Get New Link "<<client_ip<<" : "<<port<<" send a message"<<endl;
           Task task(sock_fd,client_ip,port);
           tp_->Push(task);
        }
    }

    //多线程版本
    // bool Start()
    // {
    //     signal(SIGCHLD,SIG_IGN);
    //     while(1)
    //     {
    //         struct sockaddr_in peer;
    //         memset(&peer,0,sizeof(peer));
    //         socklen_t len=sizeof(peer);
    //         int sock_fd=accept(listen_fd_,(struct sockaddr*)&peer,&len);
    //         if(sock_fd < 0)
    //         {
    //             perror("Accept TCP Socket Failed\n");
    //             continue;
    //         }
    //         std::string client_ip=inet_ntoa(peer.sin_addr);
    //         int port=ntohs(peer.sin_port);
    //         cout<<"Get New Link "<<client_ip<<" : "<<port<<" send a message"<<endl;
    //         pid_t pid= fork();
    //         if(pid ==0)
    //         {
    //             Service(sock_fd,client_ip,port);
    //             close(listen_fd_);
    //             exit(0);
    //         }
    //         else if(pid > 0)
    //         {
    //             close(sock_fd);
    //         }
    //     }
    // }
    private:
    int listen_fd_;
    std::string ip_;
    int port_;
    ThreadPool<Task>* tp_;
};